<?php

class SJB_CategorySearcher_Tree extends SJB_AbstractCategorySearcher
{
	public $tree_values;
	public $parent;

	public function SJB_CategorySearcher_Tree($field)
	{
		parent::SJB_AbstractCategorySearcher($field);
		$this->tree_values = SJB_ListingFieldTreeManager::getTreeValuesAsArrayWithChildBySID($field['sid']);
		$this->parent = array_keys($this->tree_values);
		$this->field = $field;
	}

	protected function _getCountsByItems($items)
	{
		$res = array();
		foreach($items as $item) {
			$itemArray = explode(',', $item['caption']);
			foreach ($itemArray as $val) {
				$res[$val]['listing_sid'][] = $item['object_sid'];
			}
		}
		return $res;
	}

 	public function getPositionSID($itemSID, &$result, $info, &$res)
    {
       	if (isset($this->tree_values[$itemSID])) {
       		if (isset($this->tree_values[$itemSID]['listing_sid'])) {
       			$count = count(array_intersect($this->tree_values[$itemSID]['listing_sid'], $info['listing_sid']));
    			$count = $count>0?count($info['listing_sid'])-$count:count($info['listing_sid']);
    			$count = $count>0?$count:0;
       			if ($count) {
	       			$this->tree_values[$itemSID]['listing_sid'] = array_merge($this->tree_values[$itemSID]['listing_sid'], $info['listing_sid']);
	       			$this->tree_values[$itemSID]['listing_sid'] = array_unique($this->tree_values[$itemSID]['listing_sid']);
       			}
       		}
       		else {
       			$this->tree_values[$itemSID]['listing_sid'] = $info['listing_sid'];
       		}
       		
			if ($this->tree_values[$itemSID]['parent_sid'] != 0 && in_array($this->tree_values[$itemSID]['parent_sid'], $this->parent)) {
				if (isset($res[$itemSID])) {
					$res[$this->tree_values[$itemSID]['parent_sid']][$itemSID] = $res[$itemSID];
					unset($res[$itemSID]);
				}
				else
					$res[$this->tree_values[$itemSID]['parent_sid']][$itemSID] = 1;
				self::getPositionSID($this->tree_values[$itemSID]['parent_sid'], $result, $info, $res);
			}
			elseif ($this->tree_values[$itemSID]['children'] == 0) {
				$result[$itemSID] = SJB_Array::get($info, 'count');
			}
			else {
				$result = self::array_merge_recursive_distinct($result, $res);
			}
        }
    }
    
	protected function _getParentSid($request_data)
	{
		$level = $this->field['treeLevel'];
		if ($level === 1)
			return 0;
		return $request_data[$this->field['field']]['tree'][$level - 1];
	}
	
	protected function _getCountBySid($sid, $counts)
	{
		$children = SJB_ListingFieldTreeManager::getTreeValuesByParentSID($this->fieldSid, $sid);
		$count = 0;
		if (isset($counts[$sid]))
			$count += $counts[$sid];

		foreach($children as $childSid => $childCaption){
			if(isset($counts[$childSid]))
				$count += $counts[$childSid];
		}
		return $count;
	}
	
    public function array_merge_recursive_distinct ( array &$array1, array &$array2 )
    {
        $merged = $array1;
        foreach ($array2 as $key => &$value) {
            if ( is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) )
                $merged [$key] = self::array_merge_recursive_distinct ( $merged [$key], $value );
            else
                $merged [$key] = $value;
        }
        return $merged;
    }

	protected function _get_Captions_with_Counts_Grouped_by_Captions($request_data)
	{
		$result = array();
		$items  = array();
		if (!empty($request_data[$this->field['field']]['tree'])) {
			$this->parent = $items = explode(',', $request_data[$this->field['field']]['tree']);
			$treeValues   = $this->tree_values;
			$this->tree_values = array();
		}
		if (SJB_Settings::getValue('enableBrowseByCounter')) {
			$sql = "`{$this->field['field']}` != ''";
			if (count($items) >1) {
				$sql = "(";
				foreach ($items as $key => $item) {
					if ($key == 0) {
						$sql .= " FIND_IN_SET('{$item}',`{$this->field['field']}`) ";
					} else {
						$sql .= " OR FIND_IN_SET('{$item}',`{$this->field['field']}`) ";
					}
					if (isset($treeValues[$item])) {
						$this->tree_values[$item] = $treeValues[$item];
					}
				}
				$sql .= ")";
			}
			$sql = "select ?w as caption, `sid` as object_sid from listings where `sid` in (?l) and {$sql}";
			$request_data['access_type'] = array(
				'accessible' => SJB_UserManager::getCurrentUserSID(),
			);
			$criteria = SJB_SearchFormBuilder::extractCriteriaFromRequestData($request_data);
			$searcher = SJB_ObjectMother::createListingSearcher();
			$ids      = $searcher->getObjectsSIDsByCriteria($criteria);
			if (count($ids) > 0) {
				$result = SJB_DB::query($sql, $this->field['field'], $ids, $this->field['field']);
			}
		}
		else {
			if (count($items) >1) {
				foreach ($items as $item) {
					$this->tree_values[$item] = $treeValues[$item];
				}
			}
			$result  = self::getTreeItems($this->tree_values, SJB_ListingFieldTreeManager::getTreeDepthBySID($this->field['sid']));
		}
		return $result;
	}

	public function getTreeItems($treeItems, $level)
	{
		foreach($treeItems as $id => $item) {
			if ($item['level'] == $level) {
				if (isset($treeItems[$item['parent_sid']])) {
					$treeItems[$item['parent_sid']]['nodes'][$id] = $item;
					unset($treeItems[$id]);
				}
			}
		}
		if ($level > 2) {
			$treeItems = self::getTreeItems($treeItems, $level-1);
		}
		return $treeItems;
	}

	protected function _decorateItems($items)
	{
		if (SJB_Settings::getValue('enableBrowseByCounter')) {
			$this->fieldSid = $this->getFieldSID($this->field['field']);
			$counts = $this->_getCountsByItems($items);
			$result = array();
			foreach ($counts as $itemSID => $info) {
				$res = array();
				self::getPositionSID($itemSID, $result, $info, $res);
			}
			$result = $this->getSortedResults($result);
			return self::_decorate($result);
		}
		$items = $this->getSortedValues($items);
		return self::_decorate($items);
	}

	protected function _decorate($items)
	{
		$html = '';
		if ($items) {
			$i18n   = SJB_I18N::getInstance();
			
			if ($this->field['homepage'] == 0) {
				$html .= '<div style="width:50%; float: left;" >';
			}
			$countItemsAtColumn = ceil(count($items)/2);
			$countItems = 0;
			foreach ($items as $id => $value) {
				if ($this->field['homepage'] == 0 && $countItems == $countItemsAtColumn) {
					$html .= '</div><div style="width:50%; float: left;">';
				}
				$html .= "\n<ul class='browse_tree' id='browse_tree_ul_{$id}'><li id='browse_tree_li_{$id}'><div>";
				
				$showCounter = false;
				if (SJB_Settings::getValue('enableBrowseByCounter')){
					$caption = $this->tree_values[$id]['caption'];
					$count ="(".count($this->tree_values[$id]['listing_sid']).")";
					$showCounter = true;
				}
				else {
					$caption = $value['caption'];
				}
				$translatedCaption = $i18n->gettext('', $caption);
				
				if ($showCounter) {
					// with counter we have array of keys and '1' values
					$class = !empty($value) ? 'arrow collapsed' : 'arrow';
					$html .= "<div class='{$class}' onclick='openLevel(\"{$id}\")' id='browse_tree_arrow_{$id}' ></div><label><a href='".SJB_System::getSystemSettings('SITE_URL')."/browse-by-".strtolower($this->field['field'])."/{$id}/".str_replace(" ", "-", htmlentities($caption, ENT_QUOTES, "UTF-8"))."'>". htmlentities($translatedCaption, ENT_QUOTES, "UTF-8").$count."</a></label></div>";
				} else {
					// without counter we have multidimensional array with 'children' value.
					$class = $value['children'] > 0 ? 'arrow collapsed' : 'arrow';
					$html .= "<div class='{$class}' onclick='openLevel(\"{$id}\")' id='browse_tree_arrow_{$id}' ></div><label><a href='".SJB_System::getSystemSettings('SITE_URL')."/browse-by-".strtolower($this->field['field'])."/{$id}/".str_replace(" ", "-", htmlentities($caption, ENT_QUOTES, "UTF-8"))."'>". htmlentities($translatedCaption, ENT_QUOTES, "UTF-8") . "</a></label></div>";
				}
				self::_decorateResults($value, $html);
				$html .= "\n</li>";
				$html .= "\n</ul>";
				$countItems++;
			}
			if ($this->field['homepage'] == 0)
				$html .= '</div>';
		}
		return $html;
	}

	protected function _decorateResults($itemArr, &$html)
	{
		$i18n   = SJB_I18N::getInstance();
		
		if (SJB_Settings::getValue('enableBrowseByCounter')) {
			if (is_array($itemArr)) {
				foreach ($itemArr as $item => $val ) {
					$caption    = $i18n->gettext('', $this->tree_values[$item]['caption']);
					$countItems = " (".count($this->tree_values[$item]['listing_sid']).")";
					if ($this->tree_values[$item]['children']) {
						$html .= "\n<ul style='display: none;' class='browse_tree' id='browse_tree_ul_{$item}'><li id='browse_tree_li_{$item}'><div>";
						$html .= "<div class='arrow collapsed' onclick='openLevel(\"{$item}\")' id='browse_tree_arrow_{$item}'></div><label><a href='".SJB_System::getSystemSettings('SITE_URL')."/browse-by-".strtolower($this->field['field'])."/{$item}/".str_replace(" ", "-", htmlentities($this->tree_values[$item]['caption'], ENT_QUOTES, "UTF-8"))."'>". htmlentities($caption, ENT_QUOTES, "UTF-8") . $countItems."</a></label></div>";
						self::_decorateResults($val, $html);
						$html .= "\n</li>";
						$html .= "\n</ul>";
					}
					else {
						$html .= "\n<ul style='display: none;' class='browse_tree' id='browse_tree_ul_{$item}'><li id='browse_tree_li_{$item}'><div><div class='arrow'></div><label><a href='".SJB_System::getSystemSettings('SITE_URL')."/browse-by-".strtolower($this->field['field'])."/{$item}/".str_replace(" ", "-", htmlentities($this->tree_values[$item]['caption'], ENT_QUOTES, "UTF-8"))."'>". htmlentities($caption, ENT_QUOTES, "UTF-8") . $countItems."</a></label></div>";
						self::_decorateResults($val, $html);
						$html .= "\n</li>";
						$html .= "\n</ul>";
					}
				}
			}
		} else {
			if (isset($itemArr['nodes'])) {
				foreach ($itemArr['nodes'] as $item => $val ) {
					$caption = $i18n->gettext('', $val['caption']);
					if ($val['children']) {
						$html .= "\n<ul style='display: none;' class='browse_tree' id='browse_tree_ul_{$item}'><li id='browse_tree_li_{$item}'><div>";
						$html .= "<div class='arrow collapsed' onclick='openLevel(\"{$item}\")' id='browse_tree_arrow_{$item}'></div><label><a href='".SJB_System::getSystemSettings('SITE_URL')."/browse-by-".strtolower($this->field['field'])."/{$item}/".str_replace(" ", "-", htmlentities($val['caption'], ENT_QUOTES, "UTF-8"))."'>". htmlentities($caption, ENT_QUOTES, "UTF-8") . "</a></label></div>";
						self::_decorateResults($val, $html);
						$html .= "\n</li>";
						$html .= "\n</ul>";
					} else {
						$html .= "\n<ul style='display: none;' class='browse_tree' id='browse_tree_ul_{$item}'><li id='browse_tree_li_{$item}'><div><div class='arrow'></div><label><a href='".SJB_System::getSystemSettings('SITE_URL')."/browse-by-".strtolower($this->field['field'])."/{$item}/".str_replace(" ", "-", htmlentities($val['caption'], ENT_QUOTES, "UTF-8"))."'>". htmlentities($caption, ENT_QUOTES, "UTF-8")."</a></label></div>";
						$html .= "\n</li>";
						$html .= "\n</ul>";
					}
				}
			}
		}
	}
	
	
	
	private function getSortedValues($values)
	{
		if (!empty($values)) {
			$fieldInfo = SJB_ListingFieldManager::getFieldInfoBySID($this->field['sid']);
			if (SJB_Array::get($fieldInfo, 'sort_by_alphabet') > 0) {
				$i18n   = SJB_I18N::getInstance();
				
				$parents = array();
				// in this place we have 'caption' with ids of children items, like '300,301,302,305' etc.
				// need to get real caption value (for children and parent) and sort by it
				foreach ($values as $key => $item) {
					$parents[] = $i18n->gettext('', $item['caption']);
					if ($item['children'] > 0) {
						// sort children by alphabet
						$sids     = array_keys($item['nodes']);
						$children = array();
						foreach ($item['nodes'] as $child) {
							$children[] = $i18n->gettext('', $child['caption']);
						}
						array_multisort($children, SORT_STRING, $sids, $item['nodes']);
						$values[$key]['nodes'] = array_combine($sids, $item['nodes']);
					}
				}
				// sort parent by alphabet
				$keys = array_keys($values);
				array_multisort($parents, SORT_STRING, $keys, $values);
				$values = array_combine($keys, $values);
			}
		}
		return $values;
	}
	
	
	private function getSortedResults($values)
	{
		if (!empty($values)) {
			$fieldInfo = SJB_ListingFieldManager::getFieldInfoBySID($this->field['sid']);
			if (SJB_Array::get($fieldInfo, 'sort_by_alphabet') > 0) {
				$i18n   = SJB_I18N::getInstance();
				
				$parents = array();
				// in this place we have 'caption' with ids of children items, like '300,301,302,305' etc.
				// need to get real caption value (for children and parent) and sort by it
				foreach ($values as $parent => $items) {
					if (!is_array($items)) {
						$items = array();
					}
					$sids       = array_keys($items);
					$parentSid  = SJB_ListingFieldTreeManager::getParentSID($parent);
					$parentInfo = SJB_ListingFieldTreeManager::getTreeItemInfoBySID($parentSid);
					$parents[]  = $i18n->gettext('', $parentInfo['caption']);
					
					// sort children by alphabet
					$children = array();
					foreach ($sids as $sid) {
						$info       = SJB_ListingFieldTreeManager::getTreeItemInfoBySID($sid);
						$children[] = $i18n->gettext('', $info['caption']);
					}
					array_multisort($children, SORT_STRING, $sids);
					$sids = array_fill_keys($sids, 1);
					
					// set to sorted sids
					$values[$parent] = $sids;
				}
				// sort parent by alphabet
				$keys = array_keys($values);
				array_multisort($parents, SORT_ASC, SORT_STRING, $keys, $values);
				$values = array_combine($keys, $values);
			}
		}
		return $values;
	}
}